
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fcntl.h>
#include <unistd.h>

#include <time.h>
#include <sys/time.h>
#include "timestamp.h"

#if !defined(BUILD_TIMESTAMP)
#error "### No BUILD_TIMESTAMP was be defined...... ###"
#endif

#ifdef __cplusplus

const unsigned long long int Lib_Timestamp::timebase = 1000000ULL;
const unsigned long long int Lib_Timestamp::timebase_ms = Lib_Timestamp::timebase / 1000ULL;
const unsigned long long int Lib_Timestamp::timebase_us = Lib_Timestamp::timebase / 1000000ULL;
const unsigned long long int Lib_Timestamp::timebase_ns = Lib_Timestamp::timebase / 1000000000ULL;

Lib_Timestamp::Lib_Timestamp(void)
{
}

Lib_Timestamp::~Lib_Timestamp(void)
{
}

/*
 * for system up time
 */
unsigned long long int Lib_Timestamp::getCurrentUpTimeNs(void)
{
	struct timespec ts = {0, 0};
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return ((unsigned long long int)ts.tv_sec * 1000000000ULL) + (ts.tv_nsec);
}

unsigned long long int Lib_Timestamp::getCurrentUpTimeUs(void)
{
	return ((unsigned long long int)getCurrentUpTimeNs() / 1000ULL);
}

unsigned long long int Lib_Timestamp::getCurrentUpTimeMs(void)
{
	return ((unsigned long long int)getCurrentUpTimeNs() / 1000000ULL);
}

unsigned long long int Lib_Timestamp::getCurrentUpTime(void)
{
	struct timespec ts = {0, 0};
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return ((unsigned long long int)ts.tv_sec);
}

/*
 * for date time
 */
unsigned long long int Lib_Timestamp::getCurrentDateTimeNs(void)
{
	// TODO: 某些应用需要纳秒级，做个假的算了
	return Lib_Timestamp::getCurrentDateTimeUs() * 1000;
}

unsigned long long int Lib_Timestamp::getCurrentDateTimeUs(void)
{
	struct timeval tv = {0, 0};
	gettimeofday(&tv, NULL);
	return ((unsigned long long int)tv.tv_sec * 1000000ULL) + (tv.tv_usec);
}

unsigned long long int Lib_Timestamp::getCurrentDateTimeMs(void)
{
	return ((unsigned long long int)getCurrentDateTimeUs() / 1000ULL);
}

unsigned long long int Lib_Timestamp::getCurrentDateTime(void)
{
	struct timeval tv = {0, 0};
	gettimeofday(&tv, NULL);
	return ((unsigned long long int)tv.tv_sec);
}

unsigned long long int Lib_Timestamp::getCurrentTime(void)
{
	return getCurrentUpTimeUs();
}

bool Lib_Timestamp::isCurrentDateTimeValid(void)
{
	unsigned long long int timestamp = strtoull(BUILD_TIMESTAMP, NULL, 0);

	return (timestamp <= Lib_Timestamp::getCurrentDateTime()) ? true : false;
}

bool Lib_Timestamp::getLocalTime(struct tm *tmloc, unsigned long long int timestamp)
{
	bool ret = false;

	time_t now;

	struct tm *t = NULL;

	now = (0 == timestamp) ? time(NULL) : timestamp;

	t = localtime(&now);

	if(NULL != t)
	{
		memcpy(tmloc, t, sizeof(*tmloc));

		ret = true;
	}

	return ret;
}

bool Lib_Timestamp::getDateTimeNumber(char *buffer, int size, unsigned long long int timestamp)
{
	bool ret = false;

	struct tm t;

	if(0 != timestamp || true == isCurrentDateTimeValid())
	{
		if(true == getLocalTime(&t, timestamp))
		{
			snprintf(buffer, size, "%04d-%02d-%02d %02d:%02d:%02d", \
									t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, \
									t.tm_hour, t.tm_min, t.tm_sec);

			ret = true;
		}
	}

	return ret;
}

bool Lib_Timestamp::getDateTimeChinese(char *buffer, int size, unsigned long long int timestamp)
{
	bool ret = false;

	struct tm t;

	if(0 != timestamp || true == isCurrentDateTimeValid())
	{
		if(true == getLocalTime(&t, timestamp))
		{
			snprintf(buffer, size, "%04d年%02d月%02d日 %02d:%02d:%02d", \
									t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, \
									t.tm_hour, t.tm_min, t.tm_sec);

			ret = true;
		}
	}

	return ret;
}

#endif
